package com.glink.manage.mqtt.service;

import com.alibaba.fastjson2.JSONObject;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.enums.MqttEnum;
import com.glink.manage.domain.VehicleInfoBean;
import com.glink.manage.domain.VehicleSyncRecordBean;
import com.glink.manage.domain.VehicleTransitRecordBean;
import com.glink.manage.dto.mqtt.CarBarrierGateBootRegDTO;
import com.glink.manage.dto.mqtt.CarBarrierGateCameraRegisterDTO;
import com.glink.manage.dto.mqtt.CarBarrierGateHeartDTO;
import com.glink.manage.dto.mqtt.CarBarrierGateResultDTO;
import com.glink.manage.mqtt.MqttService;
import com.glink.manage.mqtt.MqttSubscribeProperties;
import com.glink.manage.mqtt.common.ApiProperties;
import com.glink.manage.mqtt.common.HttpClientUtil;
import com.glink.manage.mqtt.model.MqttPicAnalyseResult;
import com.glink.manage.service.*;
import com.glink.manage.service.barriergate.BarrierGate_LianYi;
import com.glink.manage.vo.barriers.BarriersBaseVO;
import com.glink.manage.vo.mqtt.CarBarrierGateCameraRegisterVO;
import com.glink.manage.vo.mqtt.CarBarrierGateListVO;
import com.glink.manage.vo.mqtt.CarBarrierGateVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : qiushaoshan
 * @create 2024/7/30 18:49
 */
@Service
@Slf4j
public class MessageResultServiceImpl implements MessageResultService {

    private final ConcurrentHashMap<String, String> REQUEST_HOST_CACHE_MAP = new ConcurrentHashMap<>();


    @Resource
    private ApiProperties apiProperties;
    
    @Resource
    private MqttSubscribeProperties mqttSubscribeProperties;

    @Resource
    private MqttService mqttService;
    
    @Autowired
    private BarriersService barriersService;
    
    @Resource
    @Lazy
    private VehicleService vehicleService;
    
    @Autowired
    private VehicleSyncRecordService vehicleSyncRecordService;

    @Autowired
    private VehicleTransitRecordService vehicleTransitRecordService;
    
    @Autowired
    private BarrierGateService barrierGateService;
    
    @Autowired
    private BarrierGate_LianYi lianYi;
    
    @Override
    public void recordRequestId(String requestId, String ipPort) {
        this.REQUEST_HOST_CACHE_MAP.put(requestId, ipPort + "_" + System.currentTimeMillis());
    }

    @Override
    public void sendHttpPicAnalyse(MqttPicAnalyseResult result) {
        String ipPort = getAndRemoveRequestId(result.getRequestId());
        if (ipPort == null) {
            log.info("分析结果反馈忽略未登记的请求ID：{}", result.getRequestId());
            return;
        } 
        
        String url = this.apiProperties.picAnalyseNotifyDomain(ipPort);

        JSONObject res = HttpClientUtil.httpPost(url, result);
        if (HttpClientUtil.isSuccess(res)) {
            log.info("HTTP分析结果反馈接口响应成功");
        } else {
            log.error("HTTP分析结果反馈接口响应失败：{}", res);
        }
    }
 

    private String getAndRemoveRequestId(String requestId) {
        if (requestId == null) {
            return null;
        }
        String value = this.REQUEST_HOST_CACHE_MAP.remove(requestId);
        if (value == null) {
            return null;
        }

        int index = value.indexOf("_");
        if (index != -1) {
            return value.substring(0, index);
        }
        return value;
    }

    @Async
    public void messageHandler(String topic, String message) {
        if (topic == null) {
            return;
        }
        if(StringUtils.equals(topic, mqttSubscribeProperties.getSubscribe())){
            // 通用订阅消息
            publicSubscribe("", message);
        }else{
            List<String> carProductKeyList = mqttSubscribeProperties.getCarProductKeyList();
            if(CollectionUtils.isNotEmpty(carProductKeyList)){
                for (String carProductKey : carProductKeyList) {
                    if(topic.startsWith(carProductKey)){
                        int firstIndex = topic.indexOf("/");
                        int secondIndex = topic.indexOf("/", firstIndex + 1);
                        String sn = topic.substring(secondIndex + 1);
                        publicSubscribe(sn, message);
                        break;
                    }
                }
            }
        }
    }
    
    private void publicSubscribe(String sn, String message) {
        JSONObject jsonObject = JSONObject.parseObject(message);
        String cmd = "";
        if(jsonObject.containsKey("cmd")){
            cmd = jsonObject.getString("cmd");
        }
        if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.BOOT_REG.getKey())){
            CarBarrierGateBootRegDTO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateBootRegDTO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{} 响应结果解析失败：{}", cmd, message, e);
                return;
            }
            
            log.info("MQTT：设备SN：{},注册，msg_id:{}", result.getSn(), result.getMsg_id());
            CarBarrierGateVO carBarrierGateVO = new CarBarrierGateVO();
            carBarrierGateVO.setCmd(MqttEnum.CarBarrierGateCmd.BOOT_REG_RSP.getKey());
            carBarrierGateVO.setMsg_id(result.getMsg_id());
            // 设备注册
            BarriersBaseVO barriersBaseVO = barriersService.findByFactorySerialNumberAndOnLine(result.getSn());
            if(Objects.nonNull(barriersBaseVO)){
                // 设备在线
                barriersService.beOnlineByFactorySerialNumber(result.getSn());
                carBarrierGateVO.setStatus(MqttEnum.CmdStatus.OK.getKey());
                
                // 设备登录成功，则五秒后下发车辆信息
                CompletableFuture.runAsync(() -> {
                    try {
                        Thread.sleep(5000);
                        log.info("MQTT: 设备登录，初始化下发名单");
                        barrierGateService.issuedCarBySn(result.getSn());
                        
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                });

            }else{
                carBarrierGateVO.setStatus(MqttEnum.CmdStatus.FAIL.getKey());
            }

            sendMessage_lianYi(sn, carBarrierGateVO);
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.CAMERA_REGISTER.getKey())){
            // 摄像机注册
            CarBarrierGateCameraRegisterDTO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateCameraRegisterDTO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{}  响应结果解析失败：{}", cmd, message, e);
                return;
            }
            log.info("MQTT：摄像机注册SN：{},注册，msg_id:{}", result.getSn(), result.getMsg_id());
            CarBarrierGateCameraRegisterVO cameraRegisterVO = new CarBarrierGateCameraRegisterVO();
            cameraRegisterVO.setCmd(MqttEnum.CarBarrierGateCmd.CAMERA_REGISTER_RSP.getKey());
            cameraRegisterVO.setMsg_id(result.getMsg_id());
            cameraRegisterVO.setSn(result.getSn());
            cameraRegisterVO.setStatus(MqttEnum.CmdStatus.OK.getKey());
            sendMessage_lianYi(sn, cameraRegisterVO);
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.MQTT_HERAT.getKey())){
            // 心跳
            CarBarrierGateHeartDTO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateHeartDTO.class);
            } catch (Exception e) {
                log.error("MQTT： cmd:{} 响应结果解析失败：{}", cmd, message, e);
                return;
            }
            // 设备注册
            BarriersBaseVO barriersBaseVO = barriersService.findByFactorySerialNumberAndOnLine(result.getSn());
            if(Objects.nonNull(barriersBaseVO)){
                // 设备在线
                barriersService.beOnlineByFactorySerialNumber(result.getSn());
            }
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.RESULT.getKey())){
            // 结果上报
            CarBarrierGateResultDTO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateResultDTO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{},响应结果解析失败：{}", cmd, message, e);
                return;
            }

            String plateNum = result.getPlate_num();
            boolean status = false;
            if(StringUtils.isNotBlank(plateNum)){
                VehicleTransitRecordBean vehicleTransitRecordBean = new VehicleTransitRecordBean();
                // 车牌号系统有记录
                if(!StringUtils.equals(plateNum.toLowerCase(), "null")){
                    VehicleInfoBean vehicleInfoBean = vehicleService.findByLicensePlate(plateNum);
                    if(Objects.nonNull(vehicleInfoBean)){
                        vehicleTransitRecordBean.setLicensePlate(vehicleInfoBean.getLicensePlate());
                        vehicleTransitRecordBean.setOwner(vehicleInfoBean.getOwner());
                        vehicleTransitRecordBean.setOrganization(vehicleInfoBean.getOrganization());
                        vehicleTransitRecordBean.setType(vehicleInfoBean.getType());
                    }
                }
                
                if(StringUtils.isBlank(vehicleTransitRecordBean.getLicensePlate())){
                    vehicleTransitRecordBean.setLicensePlate(result.getPlate_num());
                }

                vehicleTransitRecordBean.setCarInout(result.getInout());
                vehicleTransitRecordBean.setVehicleType(result.getVehicle_type());
                vehicleTransitRecordBean.setCarColor(result.getCar_color());
                vehicleTransitRecordBean.setCarLogo(result.getCar_logo());
                vehicleTransitRecordBean.setPlateVal(result.isPlate_val() ? BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01 : BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                vehicleTransitRecordBean.setPlateColor(result.getPlate_color());
                vehicleTransitRecordBean.setPlateEncryptionState(String.valueOf(result.getPlate_encryption_state()));
                vehicleTransitRecordBean.setResultType(result.getType());

                vehicleTransitRecordBean.setUtcTs(result.getUtc_ts());
                if(StringUtils.isNotBlank(result.getLocal_time())){
                    try {
                        FastDateFormat instance = FastDateFormat.getInstance("yyyy/MM/dd HH:mm:ss");
                        Date parse = instance.parse(result.getLocal_time());
                        vehicleTransitRecordBean.setLocalTime(parse);
                    }catch (Exception e){
                        log.error("MQTT：车辆道闸记录：本地时间格式化异常");
                    }
                }
                
                // 设备信息
                if(StringUtils.isNotBlank(result.getSn())){
                    BarriersBaseVO barriersBaseVO = barriersService.findByFactorySerialNumberAndOnLine(result.getSn());
                    if(Objects.nonNull(barriersBaseVO)){
                        vehicleTransitRecordBean.setBarriersObjId(barriersBaseVO.getObjId());
                        vehicleTransitRecordBean.setDevSno(result.getSn());
                        vehicleTransitRecordBean.setConstructionWorkObjId(barriersBaseVO.getConstructionWorkObjId());
                        vehicleTransitRecordBean.setConstructionWorkSiteObjId(barriersBaseVO.getConstructionWorkSiteObjId());
                    }
                }
                
                vehicleTransitRecordBean.setObjId(BaseCommonUtils.generateUUID());

                try {
                    status = vehicleTransitRecordService.save(vehicleTransitRecordBean);    
                }catch (Exception e){
                    e.printStackTrace();
                    log.error("MQTT：车辆道闸：结果上送，异常，licensePlate：{}", vehicleTransitRecordBean.getLicensePlate(), e);
                }
            }

            CarBarrierGateVO carBarrierGateVO = new CarBarrierGateVO();
            carBarrierGateVO.setCmd(MqttEnum.CarBarrierGateCmd.RESULT_RSP.getKey());
            carBarrierGateVO.setMsg_id(result.getMsg_id());
            if(status){
                carBarrierGateVO.setStatus(MqttEnum.CmdStatus.OK.getKey());
            }else{
                carBarrierGateVO.setStatus(MqttEnum.CmdStatus.FAIL.getKey());
            }

            sendMessage_lianYi(sn, carBarrierGateVO);
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.LIST_ADD_RSP.getKey())){
            // 名单添加应答
            CarBarrierGateListVO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateListVO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{},响应结果解析失败：{}", cmd, message, e);
                return;
            }
            // 更新车辆同步状态
            if(lianYi.listAddCache.containsKey(result.getMsg_id())) {
                List<String> platenumList = lianYi.listAddCache.get(result.getMsg_id());
                String syncStatus;
                if(StringUtils.equals(result.getStatus(), MqttEnum.CmdStatus.OK.getKey())){
                    syncStatus = BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01;
                }else{
                    syncStatus = BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02;
                }

                List<VehicleSyncRecordBean> recordBeanList = Lists.newArrayList();
                platenumList.forEach(plateNum -> {
                    VehicleSyncRecordBean recordBean = new VehicleSyncRecordBean();
                    recordBean.setObjId(BaseCommonUtils.generateUUID());
                    recordBean.setLicensePlate(plateNum);
                    recordBean.setSyncStatus(syncStatus);
                    recordBean.setDevSno(result.getSn());
                    recordBeanList.add(recordBean);
                });
                boolean status = vehicleSyncRecordService.saveBatch(recordBeanList);
                if(status && StringUtils.equals(syncStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)){
                    // 下发下一波车牌
                    barrierGateService.issuedCarBySn(result.getSn());
                }
            }
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.LIST_DELETE_RSP.getKey())){
            // 名单删除应答
            CarBarrierGateListVO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateListVO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{},响应结果解析失败：{}", cmd, message, e);
                return;
            }
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.LIST_DELETE_ALL_RSP.getKey())){
            // 名单删除应答
            CarBarrierGateListVO result;
            try {
                result = JSONObject.parseObject(message, CarBarrierGateListVO.class);
            } catch (Exception e) {
                log.error("MQTT：cmd:{},响应结果解析失败：{}", cmd, message, e);
                return;
            }
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.LIST_QUERY_REQ.getKey())){
            // 名单查询应答
            log.info("MQTT:名单查询应答：message：{}", message);
        }else if(StringUtils.equals(cmd, MqttEnum.CarBarrierGateCmd.OFFLINE.getKey())){
            // 设备离线
            log.info("MQTT:设备离线：message：{}", message);
            JSONObject offlineObj = JSONObject.parseObject(message);
            if(Objects.nonNull(offlineObj)){
                Object deviceNameObj = offlineObj.get("device_name");
                if(Objects.nonNull(deviceNameObj)){
                    String deviceName = deviceNameObj.toString();
                    barriersService.offlineByFactorySerialNumber(deviceName);
                }
            }
        }
    }

    /**
     * 发送mqtt消息--联义
     * @param obj 消息内容
     */
    @Override
    public void sendMessage_lianYi(String sn, Object obj) {
        if(StringUtils.isNotBlank(sn)){
            List<String> productKeyList = this.mqttSubscribeProperties.getCarProductKeyList();
            if(CollectionUtils.isNotEmpty(productKeyList)){
                for (String productKey : productKeyList) {
                    String topic = productKey + "/" + sn + "/" + this.mqttSubscribeProperties.getPublish();
                    topic = topic.replaceAll("//", "/");
                    this.mqttService.sendMessage(topic, obj);
                }
            }
        }else{
            this.mqttService.sendMessage(this.mqttSubscribeProperties.getPublish(), obj);
        }
    }
}
